class: title-slide, middle, right .title-text[Mapping in R] .title-sub[2: making interactive maps in R with leaflet] .title-spacer[] .title-presenter[Matt Kerlogue] .title-date[9 January 2019] --- # The data we'll be using .pull-left[ As with the first session, [introduction to mapping](static_map.html), we'll be using the Cabinet Office's [Civil Service Statistics 2019](https://www.gov.uk/government/statistics/civil-service-statistics-2019). Specifically, the [machine readable](https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/836368/Statistical-tables-Civil-Service-Statistics-2019-machine-readable-headcounts-version-V2.csv/preview) csv. ```r # download the civil service statistics data civil_service_stats_2019 <- readr::read_csv( "https://assets.publishing.service.gov.uk/ government/uploads/system/uploads/ attachment_data/file/836368/Statistical- tables-Civil-Service-Statistics-2019- machine-readable-headcounts-version-V2.csv", col_types = paste0(rep("c", 12), collapse ="")) ``` ] .pull-right[  ] --- # Leaflet .pull-left[ The `{leaflet}` package allows R to work with the [Leaflet.js](https://leafletjs.com/) library to enable interactive mapping. ```r leaflet() %>% addTiles() %>% addMarkers(lat = 51.501861, lng = -0.129260, popup = "1 Horse Guards Road", ) %>% setView(lat = 51.501861, lng = -0.129260, zoom = 15) ``` ] .pull-right[
] --- .pull-left[ We'll use data from Table 15 of the Civil Service Statistics, which shows the number of civil servants working in NUTS3* areas. ```r cs_nuts3 <- cs19_t15 %>% filter(category_1 != "All employees", category_2 == "All employees", category_4 == "Total") %>% group_by(category_1) %>% summarise_at(vars(value), sum, na.rm = TRUE) %>% rename(NUTS318NM = category_1) %>% full_join(nuts3_codes) %>% mutate(pc = formattable::percent( value/445480), value = formattable::comma(value, digits = 0)) ``` .small[ \* NUTS3 are groupings of local authorities that have a population size of between 150,000 and 800,000 residents. ] ] .pull-right[ ``` ## # A tibble: 181 x 5 ## NUTS318NM value NUTS318CD FID pc ## <chr> <formttb> <chr> <int> <formt> ## 1 Aberdeen City and Aberdeenshire 1,720 UKM50 50 0.39% ## 2 Angus and Dundee City 1,970 UKM71 65 0.44% ## 3 Antrim and Newtownabbey 270 UKN13 112 0.06% ## 4 Ards and North Down 230 UKN09 104 0.05% ## 5 Armagh City, Banbridge and Craigavon 50 UKN07 98 0.01% ## 6 Barking & Dagenham and Havering 480 UKI52 149 0.11% ## 7 Barnet 1,370 UKI71 155 0.31% ## 8 Barnsley, Doncaster and Rotherham 3,010 UKE31 67 0.68% ## 9 Bath and North East Somerset, North Somers… 11,790 UKK12 4 2.65% ## 10 Bedford 810 UKH24 131 0.18% ## # … with 171 more rows ``` ] --- .pull-left[ To map the data we need to download the releant spatial data from the Geoportal and merge it with our statistical data ```r nuts3_spdf <- geojson_read("https://opendata.arcgis.com/datasets/" "473aefdcee19418da7e5dbfdeacf7b90_4.geojson", what = "sp") leaf_dt <- sp::merge(nuts3_spdf, cs_nuts3, by.x = "nuts318cd", by.y = "NUTS318CD") ``` ] .pull-right[ ``` ## # A tibble: 179 x 13 ## nuts318cd objectid nuts318nm bng_e bng_n long lat st_areashape ## <chr> <int> <chr> <int> <int> <dbl> <dbl> <dbl> ## 1 UKC11 1 Hartlepo… 444952 522016 -1.31 54.6 301455300. ## 2 UKC12 2 South Te… 461718 519597 -1.05 54.6 302770021. ## 3 UKC13 3 Darlingt… 428029 515649 -1.57 54.5 198812779. ## 4 UKC14 4 Durham CC 410381 532242 -1.84 54.7 2233981862. ## 5 UKC21 5 Northumb… 395323 600699 -2.08 55.3 5029869562. ## 6 UKC22 6 Tyneside 425849 561221 -1.60 54.9 406969291. ## 7 UKC23 7 Sunderla… 436470 551525 -1.43 54.9 136080079. ## 8 UKD11 8 West Cum… 315410 516775 -3.31 54.5 2070779485. ## 9 UKD36 13 Greater … 364877 405611 -2.53 53.5 327036757. ## 10 UKD37 14 Greater … 388282 410213 -2.18 53.6 401002029. ## # … with 169 more rows, and 5 more variables: st_lengthshape <dbl>, ## # NUTS318NM <chr>, value <formttbl>, FID <int>, pc <formttbl> ``` ] --- .pull-left[ ```r leaflet(leaf_dt) %>% addTiles() %>% addPolygons() ``` .small[ Now we can feed our merge spatial and statistical data to leaflet: 1. Call leaflet 2. Add tiles (your 'background' map) 3. Add polygons ] ] .pull-right[
] --- .pull-left[ .small[ The default set of 'tiles' is from the Open Street Map project, but there are a large number of other providers that you can access through the `leaflet::addProviderTiles()` function and the `leaflet::providers` object. On the right here are six options: 1. Open Street Map (the default) 2. ESRI National Geographic World Map 3. CartoDB Positron 4. CartoDB DarkMatter 5. Stamen 6. Stamen Watercolour Going forward we'll use the CartoDB Positron map as this provides a neutral background - we're interested in some geographic signposting to help people place the data, but ultimately we're visualising choropleth data so we don't need the full detail provdied by a traditional "street map". ] ] .pull-right[
] --- .pull-left[ ```r leaflet(leaf_dt) %>% * addProviderTiles(providers$CartoDB.Positron) %>% addPolygons() ``` .small[ We've replaced `addTiles()` with a call to `addProviderTiles` and called the CartoDB refernece data stored in the `providers` object. ] ] .pull-right[
] --- .pull-left[ ```r leaflet(leaf_dt) %>% addProviderTiles(...) %>% * addPolygons(color = "#aaaaaa", * weight = 1, * fillColor = ~bincol(value), * fillOpacity = 0.8) ``` .small[ We've now expanded our call to addPolygons to: 1. change the polygon border line colour and line weight 2. change the polygon fill colour according to a custom function `bincol` 3. change the transparency of the fill to 20% (0.8 = 1-0.2) `bincol` is a function that applies colour coding from the `leaflet::colorBin` function factory. ] ```r bincol <- colorBin( palette = "YlGnBu", domain = leaf_dt$value, bins = c(0, 500, 1000, 2500, 5000, 7000, 40000, 50000), pretty = FALSE, na.color = "#eeeeee") ``` ] .pull-right[
] --- .pull-left[ ```r leaflet(leaf_dt) %>% addProviderTiles(...) %>% addPolygons(...) %>% * addLegend(position = "topright", * pal = bincol, * values = ~leaf_dt$value, * title = "Headcount", * opacity = 0.8) ``` .small[ We can also add a legend that tells the viewer what the colours actually mean. ] ] .pull-right[
] --- .pull-left[ ```r leaflet(leaf_dt) %>% addProviderTiles(...) %>% addPolygons(..., * popup = ~paste(NUTS318NM, value, sep = ": ")) addLegend(...) ``` .small[ The legend tells us the broad category... but what about a specific area, wouldn't it be great to be able to click on an area and find out their underlying value. We can do that by adding the `popup` argument to `addPolygons`. You can provide a specific column in your data or, as shown here, paste columns together. ] ] .pull-right[
] --- .pull-left[ ```r leaflet(leaf_dt) %>% addProviderTiles( * providers$CartoDB.PositronNoLabels) %>% * addMapPane("dt", zIndex = 410) %>% * addMapPane("labs", zIndex = 420) %>% addPolygons(..., * options = pathOptions(pane = "dt")) %>% * addProviderTiles( * providers$CartoDB.PositronOnlyLabels, * options = * providerTileOptions(pane = "labs")) %>% addLegend(...) ``` .small[ Just like `ggplot2::ggplot()` the elements in leaflet are additive, so each call builds on the next. This means that we can't really see things like place labels that might be helpful. What we can do though, is use a version of the tiles that excludes the labels as our basemap, add our statistical data, and then add the labels on top. We also need to create a separate "pane" for our data and the labels, this ensures that the labels definitely sit on top of the data. ] ] .pull-right[
] --- .pull-left[ ```r leaflet(leaf_dt) %>% addProviderTiles(...) %>% addMapPane(...) %>% addPolygons(...) %>% * addPolygons( * data = london_spdf, * color = "#F47738", * opacity = 1, * weight = 2, * fill = FALSE, * group = "London", * options = pathOptions(pane = "dt")) %>% addProviderTiles(...) %>% addLegend(...) %>% * addLayersControl( * overlayGroups = c("London", "Core Cities"), * position = "bottomright", * options = * layersControlOptions(collapsed = FALSE)) %>% * hideGroup(c("London", "Core Cities")) ``` .small[ Finally, we can also add additional data layers. Here we are adding outlines for London and the 10 "Core Cities", we've also added a control that allows these outlines to be turned on and off by the viewer. ] ] .pull-right[
] --- .pull-left[ This example is based on an interactive map and datatables that have been produced to help Civil Service Local and the Places for Growth programme. You can view the full interactive document here: https://co-analysis.github.io/csmapping/cs_lad_2019.html. ] .pull-right[  ]